from loguru import logger
import uuid
import random
import datetime
import time
import json
import re
import copy


class DateEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return obj.strftime("%Y-%m-%d %H:%M:%S")
        else:
            return json.JSONEncoder.default(self, obj)


# 生成字符串拼接自增函数
def random_str(name='测试'):
    return str(name) + str(random.randint(1000, 9999)) + str(random.randint(100001, 999999))


# 生成uuid
def testuuid():
    return uuid.uuid1()


# 生成固定长度的数字，默认5位数字
def random_int(len=5):
    try:
        result = random.randint(pow(10, int(len)), pow(10, (int(len) + 1)) - 1)
    except Exception as e:
        raise e
    return result


# 生成随机字符串，默认5位
def testrandomstr(len=5):
    try:
        str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
        result = "".join(random.sample(str, int(len)))
    except Exception as e:
        raise e
    return result


# 获取当前时间戳
def time_stamp(t=1):
    return round(time.time() * t)


# 获取当前时间默认格式%Y-%m-%d %H:%M:%S
def current_time(format="%Y-%m-%d %H:%M:%S"):
    result = datetime.datetime.now().strftime(format)
    return result


# 获取当前或历史或未来时间戳
def his_stamp(day=0, hour=0, level=1, format="%Y-%m-%d %H:%M:%S.%f"):
    tmp = datetime.datetime.now() + datetime.timedelta(days=day) + datetime.timedelta(hours=hour)
    res = tmp.strftime(format)
    print(res)
    new_time = datetime.datetime.strptime(res, format)
    result = round(new_time.timestamp() * level)
    return result


# 获取过去的或将来的时间，+是将来时间， -是过去的时间，默认是当前时间，格式默认%Y-%m-%d %H:%M:%S
def his_time(day=0, hour=0, format="%Y-%m-%d %H:%M:%S"):
    try:
        tmp = datetime.datetime.now() + datetime.timedelta(days=day) + datetime.timedelta(hours=hour)
        result = tmp.strftime(format)
        return result
    except Exception as e:
        raise e


# 获取过去或未来时间
def his_date(day=0, format="%Y-%m-%d"):
    try:
        tmp = datetime.datetime.now() + datetime.timedelta(days=day)
        result = tmp.strftime(format)
        return result
    except Exception as e:
        raise e


# 生成一个随机id,使用当前时间+时间戳+5位的随机数组成
def randomid():
    return f"{current_time(format='%Y%m%d%H%M%S')}{time_stamp()}{random_int(5)}"


def ispartner(platcode):
    xxxxxx = ['TAOBAO', 'YOUZAN', 'JOS', 'WEIXIN']
    if str.upper(platcode) in xxxxxx:
        return "xxxxxx"
    else:
        raise Exception("你的数据是线下平台，需要给出线下平台的partner")


def version():
    return current_time("%Y%m%d%H%M%S")


# 检查字符串是否是函数的格式
def checkisfun(field):
    ptn = '^\w+\({1}.*\)$'
    if re.search(ptn, field):
        return True
    else:
        return False


'''
    @功能： 支持替换函数及自定义的value值
    string: 需要替换的字符串dd
    value: 替换的值，可以为空
    return: 返回替换后的结果
'''


def regreplace(string, value=None):
    try:
        string = str(string)
        value = eval(value) if value is not None and isinstance(value, str) else value
    except Exception as e:
        return string

    ptn = re.compile("\$\{{1}.*?\}{1}", re.S)
    ptnresult = ptn.findall(string)
    if ptnresult is not None:
        for content in ptnresult:
            param = content[2:-1].strip()
            try:
                if checkisfun(param):
                    newvalue = eval(param)
                else:
                    newvalue = str(value[param])
            except Exception as e:
                newvalue = content
            string = re.sub(r"\$\{{1}.*?\}{1}", newvalue, content, 1)
    return string


'''
    extractkey: 需要提取的表达式，从中匹配key
    extractvalue：需要提取的值，从中匹配value
    return: 返回字典格式结果
'''


def extractparam(extractkey, extractvalue):
    '''
    响应结果参数提取
    :param extractkey:提取规则
    :param extractvalue:响应结果
    :return:
    '''
    try:
        extractvalue = json.loads(extractvalue)
    except:
        print('响应结果为空')
    finally:
        value = str(extractkey)
        rc = re.compile("\$\{(.*?)\}\s*\=\s*((\[.*?\])+)", re.S)
        reresult = rc.findall(value)
        extractresult = {}
        for content in reresult:  # 匹配格式 res[0]为键 res[1] 为index
            try:
                extractresult[content[0]] = eval(f"{extractvalue}{content[1]}")
            except Exception as e:
                logger.info(f"参数{content}转换异常请检查{e}")
        logger.info(f"参数提取结果：{extractresult}")
        return extractresult


def findparam(param, value=None):
    '''
    请求参数变量函数匹配替换
    :param param:
    :param value:
    :return:
    '''
    try:
        if len(str(param).split('|')) == 1:
            logger.info(f"参数{param}格式输入不正确，缺少引用用例")
            return False
        else:
            paramname = str(param).split('|')[0].strip()
            caseindex = str(param).split('|')[1].strip()
            if not isinstance(value, dict):
                value = eval(value)
            key = f"case_{caseindex}"
            result = value[key][paramname]
            return result
    except Exception as e:
        logger.error(f"参数解析出错{e.args}")


def regparam(string, value=None):
    '''
    结果转换
    :param string: 用例
    :param value: 当前变量
    :return:
    '''
    try:
        string = str(string)
        while re.search('\@\{{1}(.*?)\}{1}', string, re.M | re.S):
            res = re.search("\@\{{1}(.*?)\}{1}", string, re.M | re.S)
            param = string[res.regs[0][0]:res.regs[0][1]][2:-1].strip()
            if checkisfun(param):
                newvalue = eval(param)
            else:
                newvalue = findparam(param, value)
                if not newvalue:
                    break
            string = string[0:res.regs[0][0]] + str(newvalue) + string[res.regs[0][1]:]
        logger.info(f"转换结果：{string}")
    except Exception as e:
        logger.info(f"函数转换异常{e.args}")
    return string


def find_all_param(data):
    try:
        string = str(data)
        res = re.findall('\$\{{1}.*?\}{1}', string, re.M | re.S)
    except Exception as e:
        logger.info(f"函数转换异常{e.args}")
    return res


def is_fun(param):
    # ptn = '^\$(.*?)({1}.*\)$'
    ptn = '\${{1}(.*?)\({1}(.*?)\){1}(.*?)}{1}'
    if re.search(ptn, param):
        return True
    else:
        return False


def rep_fun(data, param):
    tmp_param = param[2:-1].strip()
    result = data.replace(param, str(eval(tmp_param)), 1)
    return result


def is_table_name(param):
    tmp_param = param[2:-1].strip()
    if '|' in tmp_param:
        return False
    else:
        return True


def rep_table_name(data, param):
    tmp_param = param[2:-1].strip()
    result = data.replace(param, str(tmp_param), 1)
    return result


def is_param(param):
    tmp_param = param[2:-1].strip()
    if '|' in tmp_param:
        return True
    else:
        return False


def rep_param(data, param, rep_value=None):
    try:
        tmp_param = param[2:-1].strip()
        split_result = tmp_param.split("|")
        if len(split_result) != 2:
            logger.info(f"参数{param}的书写格式错误")
        if isinstance(rep_value, dict) and split_result[0].strip() in rep_value.keys():
            value = rep_value[split_result[0].strip()]
        else:
            value = split_result[1].strip()
        result = data.replace(param, value, 1)
        return result
    except Exception as ex:
        logger.info(f"参数{param}转换出错{ex}")


def find_var_param(data):
    result = []
    ptn = "\$\{{1}(.*?)\|(.+?)\}{1}"
    find_result = re.findall(ptn, data)
    key_list = []
    for item in find_result:
        if item[0] not in key_list:
            tem_dic = {"key": str(item[0]).strip(), "value": str(item[1]).strip()}
            result.append(tem_dic)
            key_list.append(item[0])
        else:
            logger.info(f"{item[0]}参数已经存在不处理")
    return result


def replace_script(data, param_list, rep_value=None):
    try:
        tmp_data = copy.deepcopy(data)
        for param in param_list:
            if is_fun(param):
                tmp_data = rep_fun(tmp_data, param)
            elif is_table_name(param):
                tmp_data = rep_table_name(tmp_data, param)
            elif is_param(param):
                tmp_data = rep_param(tmp_data, param, rep_value)
            else:
                tmp_data = f"{param}替换异常"
    except Exception as ex:
        return ex
    logger.info(f"字符串【{data}】替换的结果是【{tmp_data}】")
    return tmp_data

#
# if __name__ == '__main__':
#     # info = {'case_check': '{"msg":"发布成功!"}', 'case_id': 'cb_4', 'case_method': 'GET', 'case_name': '模板发布1-ual请求', 'case_on_off': 'YES', 'case_path': 'contentUrl-ual', 'case_relation_id': None, 'case_relation_param': "${random}=['random']", 'case_request_data': '{}', 'case_status': 0, 'case_tag': '测试用例', 'case_url': 'contentmanage/v1/content/publish/${cid | cb_3}?componentSet="image,text"', 'created': 'Thu, 20 May 2021 15:41:50 GMT', 'id': 457, 'modified': 'Thu, 20 May 2021 15:41:50 GMT', 'project_id': 45, 'service_id': 15, 'template_check': '', 'template_name': '', 'template_param': '', 'template_relation_param': '', 'version_id': 48}
#     # val = {'case_cb_3': {'cid': 41805}}
#     info="${shorturl2}=[0]['ltz166']"
#     val = '[{"ltz166":"BAZHrb"}]'
#     rs = extractparam(info,val)
#     print(rs)
